package limit;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import commomresult.CommonResult;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 在Interceptor拦截器中实现
 * @author gaofeng
 */
@Component
public class FangshuaInterceptor extends HandlerInterceptorAdapter {

    @Resource
    private RedisTemplate redisTemplate ;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;

            AccessLimit methodAnnotation = method.getMethodAnnotation(AccessLimit.class);
            if (Objects.isNull(methodAnnotation)) {
                return true ;
            }
            Integer seconds = methodAnnotation.seconds() ;

            Integer maxCounts = methodAnnotation.maxCount();

            boolean login = methodAnnotation.needLogin();

            String key = request.getRequestURI() ;

            if (login) {
                // 获取登录的session判断
                key+=""+"1";
            }
            if (isLimit(request, methodAnnotation)) {
                resonseOut(response, new CommonResult());
            }
           /* // 从redis取出用户的访问次数
            Accesskey accesskey = AccessKey.withExpire(seconds) ;
            Integer count = redisTemplate.opsForValue().get(accesskey, key) ;
            if (Objects.equals(0, count)) {
                // 第一次访问
                redisTemplate.opsForValue().set(accesskey, key, 1);
            } else if (count < maxCounts) {
                redisTemplate.opsForValue().increment(accesskey, key) ;
            } else {
                // 超出访问次数
                render(response, "1") ;
                return false ;
            }*/
        }
        return true ;
    }


    //判断请求是否受限
    public boolean isLimit(HttpServletRequest request, AccessLimit requestLimit){
        // 受限的redis 缓存key ,因为这里用浏览器做测试，我就用sessionid 来做唯一key,如果是app ,可以使用 用户ID 之类的唯一标识。
        String limitKey = request.getServletPath()+request.getSession().getId();
        // 从缓存中获取，当前这个请求访问了几次
        Integer redisCount = (Integer) redisTemplate.opsForValue().get(limitKey);
        if(redisCount == null){
            //初始 次数
            redisTemplate.opsForValue().set(limitKey,1,requestLimit.seconds(), TimeUnit.SECONDS);
        }else{
            if(redisCount.intValue() >= requestLimit.maxCount()){
                return true;
            }
            // 次数自增
            redisTemplate.opsForValue().increment(limitKey);
        }
        return false;
    }

    /**
     * 回写给客户端
     * @param response
     * @param result
     * @throws IOException
     */
    private void resonseOut(HttpServletResponse response, CommonResult result) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = null ;
        String json = result.toString() ;
        out = response.getWriter();
        out.append(json);
    }
 /*   private void render(HttpServletResponse response, String cm)throws Exception {
        response.setContentType("application/json;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        String str  = JSON.toJSONString("错误");
        out.write(str.getBytes("UTF-8"));
        out.flush();
        out.close();
    }*/
}
